﻿/* Autor: Achim Schnell */

using System;
using System.Linq;
using System.Reflection;
using AppFx.ComponentModel.Descriptive;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Tests.ComponentModel.Descriptive
{
	[TestClass]
	public class Test_PropertyDescriptorEx
	{
		[TestMethod]
		[Description("Testet, ob der PropertyDesciptorEx erstellt werden kann.")]
		public void Can_CreatePropertyDescriptorEx()
		{
			CustomType obj = new CustomType();
			Type objType = obj.GetType();
			PropertyInfo[] pis = objType.GetProperties();

			PropertyDescriptorX descriptor = new PropertyDescriptorX(objType, pis[0]);
		}

		[TestMethod]
		[Description("Testet, ob der PropertyDesciptorEx das ReadOnlyAttribut verarbeiten kann.")]
		public void Can_ConsiderReadOnlyAttribute()
		{
			CustomType obj = new CustomType();
			Type objType = obj.GetType();
			PropertyInfo[] pis = objType.GetProperties();

			PropertyDescriptorX titleDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Title").Single());
			PropertyDescriptorX nameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Name").Single());
			PropertyDescriptorX lastNameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "LastName").Single());

			Assert.IsTrue(true == titleDescriptor.IsReadOnly);
			Assert.IsTrue(false == nameDescriptor.IsReadOnly);
			Assert.IsTrue(false == lastNameDescriptor.IsReadOnly);
		}

		[TestMethod]
		[Description("Testet, ob der PropertyDesciptorEx das BrowsableAttribut verarbeiten kann.")]
		public void Can_ConsiderBrowsableAttribute()
		{
			CustomType obj = new CustomType();
			Type objType = obj.GetType();
			PropertyInfo[] pis = objType.GetProperties();

			PropertyDescriptorX titleDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Title").Single());
			PropertyDescriptorX nameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Name").Single());
			PropertyDescriptorX lastNameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "LastName").Single());

			Assert.IsTrue(true == titleDescriptor.IsBrowsable);
			Assert.IsTrue(false == nameDescriptor.IsBrowsable);
			Assert.IsTrue(true == lastNameDescriptor.IsBrowsable);
		}

		[TestMethod]
		[Description("Testet, ob der PropertyDesciptorEx das DisplayNameAttribut verarbeiten kann.")]
		public void Can_ConsiderDisplayNameAttribute()
		{
			CustomType obj = new CustomType();
			Type objType = obj.GetType();
			PropertyInfo[] pis = objType.GetProperties();

			PropertyDescriptorX titleDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Title").Single());
			PropertyDescriptorX nameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Name").Single());

			Assert.IsTrue("Titel" == titleDescriptor.DisplayName);
			Assert.IsTrue("Name" == nameDescriptor.DisplayName);
		}

		[TestMethod]
		[Description("Testet, ob der PropertyDesciptorEx das CategoryAttribut verarbeiten kann.")]
		public void Can_ConsiderCategoryAttribute()
		{
			CustomType obj = new CustomType();
			Type objType = obj.GetType();
			PropertyInfo[] pis = objType.GetProperties();

			PropertyDescriptorX titleDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Title").Single());
			PropertyDescriptorX nameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Name").Single());

			Assert.IsTrue("Anrede" == titleDescriptor.Category);
			Assert.IsTrue(String.Empty == nameDescriptor.Category);
		}

		[TestMethod]
		[Description("Testet, ob der PropertyDesciptorEx das DescriptionAttribut verarbeiten kann.")]
		public void Can_ConsiderDescriptionAttribute()
		{
			CustomType obj = new CustomType();
			Type objType = obj.GetType();
			PropertyInfo[] pis = objType.GetProperties();

			PropertyDescriptorX titleDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Title").Single());
			PropertyDescriptorX nameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Name").Single());

			Assert.IsTrue("Anrede des CustomType" == titleDescriptor.Description);
			Assert.IsTrue(String.Empty == nameDescriptor.Description);
		}

		[TestMethod]
		[Description("Testet, ob der PropertyDesciptorEx das DefaultValueAttribut verarbeiten kann.")]
		public void Can_ConsiderDefaultValueAttribute()
		{
			CustomType obj = new CustomType();
			Type objType = obj.GetType();
			PropertyInfo[] pis = objType.GetProperties();

			PropertyDescriptorX titleDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Title").Single());
			PropertyDescriptorX nameDescriptor = new PropertyDescriptorX(objType, pis.Where(pi => pi.Name == "Name").Single());

			Assert.IsTrue(titleDescriptor.CanResetValue(obj));
			titleDescriptor.ResetValue(obj);
			Assert.IsTrue("Herr" == obj.Title);

			Assert.IsFalse(nameDescriptor.CanResetValue(obj));
		}

		internal class CustomType
		{
			[System.ComponentModel.ReadOnly(true)]
			[System.ComponentModel.Browsable(true)]
			[System.ComponentModel.DisplayName("Titel")]
			[System.ComponentModel.Category("Anrede")]
			[System.ComponentModel.Description("Anrede des CustomType")]
			[System.ComponentModel.DefaultValue("Herr")]
			public string Title { get; set; }

			[System.ComponentModel.ReadOnly(false)]
			[System.ComponentModel.Browsable(false)]
			public string Name { get; set; }

			public string LastName { get; set; }
		}
	}

	public class PropertyDescriptorX : PropertyDescriptorEx
	{
		public PropertyDescriptorX(Type componentType, PropertyInfo propertyInfo)
			: base(componentType, propertyInfo) { }

		public override object GetValue(object component)
		{
			return PropertyInfo.GetValue(component, null);
		}

		public override void SetValue(object component, object value)
		{
			PropertyInfo.SetValue(component, value, null);
		}
	}
}
